package com.distributer.delayqueue.autoconfigure;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

import redis.clients.jedis.Jedis;

import com.distributer.delayqueue.delayqueue.JobOperationService;
import com.distributer.delayqueue.delayqueue.bucket.BucketQueueManager;
import com.distributer.delayqueue.delayqueue.event.EventBus;
import com.distributer.delayqueue.delayqueue.event.JobEventListener;
import com.distributer.delayqueue.delayqueue.event.RdbStore;
import com.distributer.delayqueue.delayqueue.event.RedisJobEventListener;
import com.distributer.delayqueue.delayqueue.impl.JobOperationServiceImpl;
import com.distributer.delayqueue.delayqueue.ready.ReadyQueueManager;
import com.distributer.delayqueue.delayqueue.support.RedisDistributedLock;
import com.distributer.delayqueue.delayqueue.support.RedisQueueProperties;
import com.distributer.delayqueue.delayqueue.support.RedisSupport;


@Configuration
@EnableConfigurationProperties(RedisQueueProperties.class)
@ConditionalOnClass(value = { Jedis.class, RedisQueueImpl.class })
public class RedisQueueAutoConfiguration {

	public static final Logger LOGGER = LoggerFactory.getLogger(RedisQueueAutoConfiguration.class);
	@Autowired
	private DruidConfig druidConfig;
	@Autowired
	private RedisQueueProperties properties;
	@Autowired
	private StringRedisTemplate template;

	@Bean
	public RedisSupport redisSupport() {
		RedisSupport support = new RedisSupport();
		support.setTemplate(template);
		return support;
	}

	/**
	 * 分布式锁
	 */
	@Bean
	@Autowired
	public RedisDistributedLock redisDistributedLock(RedisSupport redisSupport) {
		return new RedisDistributedLock(redisSupport);
	}

	@Bean
	@Autowired
	public JobOperationService JobOperationService(RedisSupport redisSupport) {
		JobOperationServiceImpl jobOperationService = new JobOperationServiceImpl();
		jobOperationService.setRedisSupport(redisSupport);
		jobOperationService.setRedisQueueProperties(properties);
		return jobOperationService;
	}

	@Bean
	@Autowired
	public BucketQueueManager BucketQueueManager(JobOperationService jobOperationService, RedisDistributedLock lock) {
		BucketQueueManager manager = new BucketQueueManager();
		manager.setRedisQueueProperties(properties);
		manager.setJobOperationService(jobOperationService);
		manager.setLock(lock);
		return manager;
	}

	@Bean
	public RdbStore rdbStore(DataSource dataSource) {
		try {
			return new RdbStore(dataSource);
		} catch (Exception e) {
			LOGGER.error(e.getMessage());
			throw new RuntimeException(e);
		}
	}

	@Bean
	@Autowired
	public JobEventListener jobEventListener(RdbStore store) {
		RedisJobEventListener eventListener = new RedisJobEventListener();
		eventListener.setStore(store);
		EventBus.getInstance().register(eventListener);
		return eventListener;
	}

	@Bean
	@Autowired
	public ReadyQueueManager readyQueueManager(JobOperationService jobOperationService, RedisDistributedLock lock) {
		ReadyQueueManager manager = new ReadyQueueManager();
		manager.setRedisQueueProperties(properties);
		manager.setJobOperationService(jobOperationService);
		manager.setLock(lock);
		return manager;
	}

	@Bean
	@Autowired
	public RedisQueueImpl redisQueueImpl(JobOperationService jobOperationService, BucketQueueManager bucketQueueManager, ReadyQueueManager readyQueueManager) {
		RedisQueueImpl redisQueue = new RedisQueueImpl();
		redisQueue.setRedisQueueProperties(properties);
		redisQueue.setJobOperationService(jobOperationService);
		redisQueue.setBucketQueueManager(bucketQueueManager);
		redisQueue.setReadyQueueManager(readyQueueManager);
		readyQueueManager.setDelayQueue(redisQueue);
		return redisQueue;
	}

}
